#ifndef VECTOR3_H
#define VECTOR3_H

#include <math.h>

namespace Eternal
{
	namespace Core
	{
		class Vector3
		{
			public:
				
				/*******************************************************/
				Vector3();
				
				/* Copy constructors */
				Vector3(const float fx, const float fy, const float fz);
				Vector3(const Vector3 &v);
				
				~Vector3();
				
				
				
				/* Negate the vector */
				inline Vector3 operator -() const {
					return Vector3(x, y, z);
				}
				/*******************************************************/
				
				
				/*******************************************************/
				
				inline float Magnitude() const
				{
					return sqrtf((x * x) + (y * y) + (z * z));
				}
				
				inline void Normalize()
				{
					const float m = Magnitude();
					
					x /= m;
					y /= m;
					z /= m;
				}
				
				inline float DotProduct(const Vector3 &v) const
				{
					return (x * v.x) + (y * v.y);
				}
				
				
				inline Vector3 CrossProduct(const Vector3 &v) const
				{
					return Vector3( y * v.z - z * v.y,
									z * v.x - x * v.z,
									x * v.y - y * v.x );
				}
				
				/*******************************************************/
				
				/* Addition by scalar */
				inline void operator +=(const float scalar)
				{
					x += scalar;
					y += scalar;
					z += scalar;
				}
				
				/* Addition by vector */
				inline void operator +=(const Vector3 &v)
				{
					x = v.x;
					y = v.y;
					z = v.z;
				}
				
				/* Assign by scalar */
				inline void operator =(const float scalar)
				{
					x = y = z = scalar;
				}
				
				/* Assign by vector */
				inline void operator =(const Vector3 &v)
				{
					x = v.x;
					y = v.y;
					z = v.z;
				}
				
				/* Multiplication by vector */
				inline void operator *=(const Vector3 &v)
				{
					x *= v.x;
					y *= v.y;
					z *= v.z;
				}
				
				/* Multiplication by scalar */
				inline void operator *=(const float scalar)
				{
					x *= scalar;
					y *= scalar;
					z *= scalar;
				}
				
				/*******************************************************/
				
				/* Scalar arithmetic */
				inline Vector3 operator *(const float scalar) const
				{
					return Vector3(x * scalar, y * scalar, z * scalar);
				}
				
				inline Vector3 operator +(const float scalar) const
				{
					return Vector3(x + scalar, y + scalar, z + scalar);
				}
				
				inline Vector3 operator -(const float scalar) const
				{
					return Vector3(x - scalar, y - scalar, z - scalar);
				}
				
				inline Vector3 operator /(const float scalar) const
				{
					return Vector3(x / scalar, y / scalar, z / scalar);
				}
				
				/*******************************************************/
				
				/* Scalar arithmetic */
				inline Vector3 operator +(const Vector3 &v) const
				{
					return Vector3(x + v.x, y + v.y, z + v.z);
				}
				
				inline Vector3 operator -(const Vector3 &v) const
				{
					return Vector3(x - v.x, y - v.y, z - v.z);
				}
				
				inline Vector3 operator *(const Vector3 &v) const
				{
					return Vector3(x * v.x, y * v.y, z * v.z);
				}
				
				inline Vector3 operator /(const Vector3 &v) const
				{
					return Vector3(x / v.x, y / v.y, z / v.z);
				}
				
				/* Distance between two vectors */
				inline float Distance(const Vector3 &v) const
				{
					const float dx = x - v.x;
					const float dy = y - v.y;
					const float dz = z - v.z;
					
					return sqrtf((dx * dx) + (dy * dy) + (dz * dz));
				}
				
				float x, y, z;
			private:
		};
	}
}

#endif
